package com.dom.invoapp.modular.service;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.dom.common.enums.CancelStatEnum;
import com.dom.common.enums.SaleOrderStatEnum;
import com.dom.common.enums.VerfyStatEnum;
import com.dom.common.exception.ServiceException;
import com.dom.common.model.standard.ResponseModel;
import com.dom.common.model.vo.sale.*;
import com.dom.invoapp.dao.entity.TmMarketOrderDetailFlow;
import com.dom.invoapp.dao.entity.TmMarketOrderFlow;
import com.dom.invoapp.dao.entity.TpPurcOrderFlow;
import com.dom.invoapp.dao.service.ITTradeDateService;
import com.dom.invoapp.dao.service.ITmMarketOrderDetailFlowService;
import com.dom.invoapp.dao.service.ITmMarketOrderFlowService;
import com.dom.invoapp.util.ComputeUtil;
import com.netflix.discovery.util.StringUtil;
import com.xiaoleilu.hutool.date.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * M_销售订单service
 * </p>
 *
 * @author zhuwei
 * @since 2018-11-18
 */
@Slf4j
@Service
public class SaleOrderService {

    @Autowired
    private ITmMarketOrderFlowService marketOrderFlowService;
    @Autowired
    private ITmMarketOrderDetailFlowService marketOrderDetailFlowService;
    @Autowired
    private ITTradeDateService tradeDateService;

    /**
     * <p>
     * 新增销售订单流水
     * </p>
     *
     * @author zhuwei
     * @since 2018-11-18
     */
    public String insertSaleOrder(M010R request){
        TmMarketOrderFlow flow = new TmMarketOrderFlow();
        BeanUtils.copyProperties(request,flow);
        flow.setDigest(request.getBillAbstract());
        flow.setSaleType(request.getSaleMode() == null ? null : Integer.valueOf(request.getSaleMode()));
        flow.setAbbrName(request.getCustName());
        flow.setMemCode(request.getMemCode());
        flow.setCustCode(request.getCustCode() == null ? null : Integer.valueOf(request.getCustCode()));
//        flow.setOrderType(request.getOrderType() == null ? null : Integer.valueOf(request.getOrderType()));
        flow.setOrderType(1);
        flow.setContCode(StringUtils.isEmpty(request.getLinkCode()) ? null : Integer.valueOf(request.getLinkCode()));
        flow.setContName(request.getLinkMan());
        flow.setContPhone(request.getLinkManTel());
        flow.setOrganCode(request.getOrgId());
        flow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        flow.setVerfyStat(VerfyStatEnum.VERFY_STAT_CONFIRMING.getCode());
        flow.setCancelStat(CancelStatEnum.CANCEL_STAT_NORMAL.getCode());
        flow.setSendDate(request.getSendDate() == null ? null : DateUtil.parse(request.getSendDate(), "yyyy-MM-dd"));
        //TODO 赋值交易日期
        flow.setMemCode(0);
        flow.setDocuMakerId(1111);
        flow.setVersion(0);
        flow.setExchDate(tradeDateService.getExchDate(0));
        boolean result = marketOrderFlowService.insert(flow);
        if (!result) {
            log.info("登记销售订单失败, result:{}", result);
            throw new ServiceException("9001", "录入销售订单数据库异常");
        }
        List<TmMarketOrderDetailFlow> list = new ArrayList<TmMarketOrderDetailFlow>();
        request.getSaleOrderDetailData().forEach(item -> {
            list.add(convertEntity(item, flow));
        });
        boolean batchResult = marketOrderDetailFlowService.insertBatch(list);
        if(!batchResult){
            log.info("录入销售订单明细失败, result:{}", batchResult);
            throw new ServiceException("9001", "录入销售订单明细数据库异常");
        }
        return flow.getId().toString();
    }

    private TmMarketOrderDetailFlow convertEntity(SaleOrderDetailInfo saleOrderDetail, TmMarketOrderFlow flow){
        TmMarketOrderDetailFlow detailFlow = new TmMarketOrderDetailFlow();
        detailFlow.setFamount(BigDecimal.ZERO);
        detailFlow.setRemAmount(BigDecimal.ZERO);
        detailFlow.setOrderId(flow.getId().toString());
        detailFlow.setAmount(saleOrderDetail.getAmount() == null ? BigDecimal.ZERO : saleOrderDetail.getAmount());
        detailFlow.setBal(ComputeUtil.computeGoodsBal(saleOrderDetail.getPrice(),saleOrderDetail.getAmount()));
        detailFlow.setDigest(saleOrderDetail.getBillAbstract());
        detailFlow.setEstOutTax(ComputeUtil.computeEstOutTax(saleOrderDetail.getPrice(),saleOrderDetail.getOutTaxRate(),saleOrderDetail.getAmount()));
//        detailFlow.setFamount(saleOrderDetail.getNoAmount());
        detailFlow.setGoodCode(saleOrderDetail.getGoodCode());
        detailFlow.setGoodName(saleOrderDetail.getGoodName());
        detailFlow.setMemCode(flow.getMemCode());
        detailFlow.setNoTaxBal(ComputeUtil.computeGoodsNoTaxBal(saleOrderDetail.getPrice(),saleOrderDetail.getAmount(),saleOrderDetail.getOutTaxRate()));
        detailFlow.setNoTaxPrice(ComputeUtil.computeNoTaxPrice(saleOrderDetail.getPrice(),saleOrderDetail.getOutTaxRate()));
//        detailFlow.setOrderId(flow.getOrderId());
        detailFlow.setOutTaxRate(saleOrderDetail.getOutTaxRate());
        detailFlow.setPrice(saleOrderDetail.getPrice());
//        detailFlow.setRemAmount(saleOrderDetail.getRemAmount());
        detailFlow.setSource(saleOrderDetail.getSource());
        detailFlow.setStandardName(saleOrderDetail.getStandardName());
        detailFlow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        detailFlow.setUnit(saleOrderDetail.getUnit());
        detailFlow.setVarietyCode(saleOrderDetail.getVarietyCode());
        detailFlow.setVarietyName(saleOrderDetail.getVarietyName());
        detailFlow.setVersion(0);
        return detailFlow;
    }

    public Page findByPage(M019R request) {
        Page<TmMarketOrderFlow> page = new Page<>();
        page.setSize(request.getPs() == 0 ? 20 : request.getPs());
        page.setCurrent(request.getPn());

        Wrapper wrapper = new EntityWrapper();
        if (!StringUtils.isEmpty(request.getCustCode())) {
            wrapper.and().eq("cust_code",request.getCustCode());
        }
        if (!StringUtils.isEmpty(request.getCustName())) {
            wrapper.and().eq("abbr_name",request.getCustName());
        }
        if (!StringUtils.isEmpty(request.getOrderType())) {
            wrapper.and().eq("order_type",request.getOrderType());
        }
        if (!StringUtils.isEmpty(request.getSaleType())) {
            wrapper.and().eq("sale_type",request.getSaleType());
        }
        if (!StringUtils.isEmpty(request.getMakerId())) {
            wrapper.and().eq("market_id",request.getMakerId());
        }
        if(request.getExchStartDate() != null && request.getExchEndDate() != null)
            wrapper.between("exch_date", DateUtil.parse(request.getExchStartDate(), "yyyy-MM-dd"), DateUtil.parse(request.getExchEndDate(), "yyyy-MM-dd"));
        if (request.getSendEndDate() != null && request.getSendStartDate() != null)
            wrapper.and().between("deli_date", DateUtil.parse(request.getSendStartDate(), "yyyy-MM-dd"), DateUtil.parse(request.getSendEndDate(), "yyyy-MM-dd"));
        if (StringUtils.isNotEmpty(request.getMakerId())) {
            wrapper.and().eq("docu_maker_id", request.getMakerId());
        }
        if(StringUtils.isNotEmpty(request.getKeyId())){
            wrapper.and().eq("id",request.getKeyId());
        }
        wrapper.and().notIn("cancel_stat", CancelStatEnum.CANCEL_STAT_CANCELED.getCode());
        List<String> orderList = new ArrayList<>();
        orderList.add("exch_date");
        orderList.add("make_date");
        wrapper.orderBy(true, orderList, false);
        return marketOrderFlowService.selectPage(page, wrapper);
    }

    public M013A findSaleDetail(M013R request){
        M019R r = new M019R();
        r.setKeyId(request.getKeyId());
        Page page = findByPage(r);
        Page<TmMarketOrderDetailFlow> pageDetail = new Page<>();
        pageDetail.setSize(request.getPs() == 0 ? 20 : request.getPs());
        pageDetail.setCurrent(request.getPn());
        M013A m013A = convertSaleFlow((TmMarketOrderFlow)page.getRecords().get(0));
        Wrapper wrapper = new EntityWrapper();
        wrapper.eq("order_id",request.getKeyId());
        pageDetail = marketOrderDetailFlowService.selectPage(pageDetail,wrapper);
        m013A = convertSaleDetail(m013A,pageDetail);
        return m013A;
    }

    private M013A convertSaleFlow(TmMarketOrderFlow flow){
        M013A m013A = new M013A();
        m013A.setKeyId(flow.getId().toString());
        m013A.setAddress(flow.getAddress());
        m013A.setBillAbstract(flow.getDigest());
        m013A.setCancelStat(Integer.toString(flow.getCancelStat()));
        m013A.setCancelTime(flow.getCancelTime() == null ? "" : DateUtil.formatDate(flow.getCancelTime()));
        m013A.setCompCode(flow.getOrganCode() == null ? "" : flow.getOrganCode().toString());
        m013A.setCustCode(flow.getCustCode() == null ? "" : flow.getCustCode().toString());
        m013A.setCustName(flow.getAbbrName());
        m013A.setSendDate(flow.getSendDate() == null ? "" : DateUtil.formatDate(flow.getSendDate()));
        m013A.setExchDate(flow.getExchDate() == null ? "" : DateUtil.formatDate(flow.getExchDate()));
        m013A.setLinkCode(flow.getContCode() == null ? "" : flow.getContCode().toString());
        m013A.setLinkMan(flow.getContName());
        m013A.setLinkManTel(flow.getContPhone());
        m013A.setMakeDate(flow.getMakeDate() == null ? "" : DateUtil.formatDate(flow.getMakeDate()));
        m013A.setMakerId(flow.getDocuMakerId() == null ? "" : flow.getDocuMakerId().toString());
        m013A.setOrderId(flow.getOrderId());
        m013A.setOrderType(flow.getOrderType() == null ? null : flow.getOrderType().toString());
        m013A.setSaleMode(flow.getSaleType() == null ? null : flow.getSaleType().toString());
        m013A.setStat(Integer.toString(flow.getStat()));
        m013A.setVerfierId(flow.getVerfierId());
        m013A.setVerfyDate(flow.getVerfyDate() == null ? "" : DateUtil.formatDate(flow.getVerfyDate()));
        m013A.setVerfyErrMsg(flow.getVerfyErrMsg());
        m013A.setVerfyStat(Integer.toString(flow.getVerfyStat()));
        m013A.setCancelStat(Integer.toString(flow.getCancelStat()));
//        m013A.setMakerName(flow.get);
        return m013A;
    }

    private M013A convertSaleDetail(M013A m013A,Page<TmMarketOrderDetailFlow> page){
        List<SaleOrderDetailInfo> list = new ArrayList<>();
        for ( TmMarketOrderDetailFlow detail :page.getRecords()
             ) {
            SaleOrderDetailInfo info = new SaleOrderDetailInfo();
            info.setOrderId(detail.getOrderId());
            info.setKeyId(detail.getId().toString());
            info.setAmount(detail.getAmount());
            info.setBal(detail.getBal());
            info.setBillAbstract(detail.getDigest());
            info.setEstOutTax(detail.getEstOutTax());
            info.setGoodCode(detail.getGoodCode());
            info.setGoodName(detail.getGoodName());
            info.setGoodSource(detail.getSource());
            info.setNoAmount(detail.getFamount());
            info.setNoTaxBal(detail.getNoTaxBal());
            info.setNoTaxPrice(detail.getNoTaxPrice());
            info.setOutTaxRate(detail.getOutTaxRate());
            info.setPrice(detail.getPrice());
            info.setRemAmount(detail.getRemAmount());
            info.setSaleOrderDetailId(detail.getGoodFlowNo() == null ? "" : detail.getGoodFlowNo().toString());
            info.setSource(detail.getSource());
            info.setStandardName(detail.getStandardName());
            info.setStat(Integer.toString(detail.getStat()));
            info.setUnit(detail.getUnit());
            info.setVarietyCode(detail.getVarietyCode());
            info.setVarietyName(detail.getVarietyName());
            list.add(info);
        }
        m013A.setSaleOrderDetailData(list);
        return m013A;
    }

    public boolean saleOrderDel(String orderId){
        TmMarketOrderFlow flow = new TmMarketOrderFlow();
        flow.setId(StringUtils.isEmpty(orderId) ? null : Integer.valueOf(orderId));
        flow.setStat(CancelStatEnum.CANCEL_STAT_CANCELED.getCode());
        Wrapper<TmMarketOrderFlow> wap = new EntityWrapper<TmMarketOrderFlow>();
        wap.eq("id",orderId);
        return marketOrderFlowService.update(flow,wap);
    }

    public ResponseModel saleOrderModify(M012R request){
        //修改销售订单流水
        boolean isture = updateSaleOrder(request);
        if(!isture){
            throw new ServiceException("8001", "修改销售订单数据库异常");
        }
        //修改销售订单明细
        isture = updateSaleOrderDetail(request);
        return new ResponseModel("RSP000000","销售订单数据修改完成！");
    }

    private boolean updateSaleOrderDetail(M012R request){
        TmMarketOrderDetailFlow flow = new TmMarketOrderDetailFlow();
        TmMarketOrderFlow orderFlow = new TmMarketOrderFlow();
        Wrapper<TmMarketOrderDetailFlow> wap = new EntityWrapper<TmMarketOrderDetailFlow>();
        Wrapper<TmMarketOrderFlow> flowWap = new EntityWrapper<TmMarketOrderFlow>();
        List<String> list = new ArrayList<String>();
        if(request.getSaleOrderDetailData() != null && 0 != request.getSaleOrderDetailData().size()){
            for (M022R detail : request.getSaleOrderDetailData() ) {
                if(StringUtils.isNotEmpty(detail.getKeyId())) list.add(detail.getKeyId());
            }
        }
        wap.notIn("id",list);
        wap.and().eq("order_id",request.getKeyId());
        //先把删除的销售订单明细流水删除delete not in orderId
        marketOrderDetailFlowService.delete(wap);
        //查询剩余销售订单明细
        List<String> detailList = marketOrderDetailFlowService.selectDetailIdByOrderId(request.getKeyId());
        //剩余明细包含上送明细则修改，否则insert
        for (M022R detail : request.getSaleOrderDetailData()) {
            TmMarketOrderDetailFlow detailFlow = toDetailFlow(detail, request);
            if (!StringUtils.isEmpty(detail.getKeyId()) &&
                    detailList.contains(detail.getKeyId())) {
                Wrapper<TmMarketOrderDetailFlow> detailIdWap = new EntityWrapper<TmMarketOrderDetailFlow>();
                detailIdWap.and().eq("id", detail.getKeyId());
                marketOrderDetailFlowService.update(detailFlow, detailIdWap);
            } else {
                marketOrderDetailFlowService.insert(detailFlow);
            }
        }
        return true;
    }

    private TmMarketOrderDetailFlow toDetailFlow(M022R detail,M012R request){
        TmMarketOrderDetailFlow flow = new TmMarketOrderDetailFlow();
        flow.setRemAmount(detail.getRemAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getRemAmount()));
        flow.setFamount(detail.getNoAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getNoAmount()));
        flow.setAmount(detail.getAmount() == null ? BigDecimal.ZERO : new BigDecimal(detail.getAmount()));
        flow.setVersion(0);
        flow.setId(StringUtils.isEmpty(detail.getKeyId()) ? null : Integer.valueOf(detail.getKeyId()));
        flow.setOrderId(request.getKeyId());
        flow.setVarietyName(detail.getVarietyName());
        flow.setVarietyCode(detail.getVarietyCode() == null ? null : Integer.valueOf(detail.getVarietyCode()));
        flow.setUnit(detail.getUnit());
        flow.setStandardName(detail.getStandardName());
        flow.setSource(detail.getSource());
        flow.setPrice(detail.getPrice() == null ? BigDecimal.ZERO : new BigDecimal(detail.getPrice()));
        flow.setOutTaxRate(detail.getOutTaxRate() == null ? BigDecimal.ZERO : new BigDecimal(detail.getOutTaxRate()));
        flow.setNoTaxBal(ComputeUtil.computeGoodsNoTaxBal(detail.getPrice(),detail.getAmount(),detail.getOutTaxRate()));
        flow.setNoTaxPrice(ComputeUtil.computeNoTaxPrice(detail.getPrice(),detail.getOutTaxRate()));
//        flow.setMemCode(request.getMemCode());
        flow.setMemCode(0);
        flow.setGoodFlowNo(detail.getOrderDetailId());
        flow.setGoodName(detail.getGoodName());
        flow.setGoodCode(detail.getGoodCode() == null ? null : Integer.valueOf(detail.getGoodCode()));
        flow.setEstOutTax(ComputeUtil.computeEstOutTax(detail.getPrice(),detail.getOutTaxRate(),detail.getAmount()));
        flow.setDigest(detail.getBillAbstract());
        flow.setBal(ComputeUtil.computeGoodsBal(detail.getPrice(),detail.getAmount()));
        flow.setStat(SaleOrderStatEnum.ORDER_STAT_WAITING.getCode());
        return flow;
    }

    private boolean updateSaleOrder(M012R request){
        TmMarketOrderFlow flow = new TmMarketOrderFlow();
        flow.setId(StringUtils.isEmpty(request.getKeyId()) ? null : Integer.valueOf(request.getKeyId()));
        flow.setCustCode(StringUtils.isEmpty(request.getCustCode()) ? null : Integer.valueOf(request.getCustCode()));
        flow.setAbbrName(request.getCustName());
//        flow.setOrderType(StringUtils.isEmpty(request.getOrderType()) ? null : Integer.valueOf(request.getOrderType()));
        flow.setSaleType(StringUtils.isEmpty(request.getSaleMode()) ? null : Integer.valueOf(request.getSaleMode()));
        flow.setContCode(StringUtils.isEmpty(request.getLinkCode()) ? null : Integer.valueOf(request.getLinkCode()));
        flow.setContName(request.getLinkMan());
        flow.setContPhone(request.getLinkManTel());
        flow.setSendDate(StringUtils.isEmpty(request.getDeliDate()) ? null : DateUtil.parseDate(request.getDeliDate()));
        flow.setAddress(request.getAddress());
        flow.setDigest(request.getBillAbstract());
        Wrapper<TmMarketOrderFlow> wap = new EntityWrapper<TmMarketOrderFlow>();
        wap.and().eq("id",request.getKeyId());
        return marketOrderFlowService.update(flow,wap);
    }

}
